今日筆者將接續昨天的內容,為這個小遊戲增加更多的功能,使得它更加的完整。
此次所新增的內容包含:
那麼就讓我們直接開始今日的內容吧!
首先先於主程式中建立一個變數 question_id,用於紀錄現在所進行到的題目編號,並於顯示結果時一併列出一個「下一題」按鈕,當按下時,題號便會增加,表示已經進行到了下一個題目:
<script setup>
const question_id = ref(1);
function nextQuestion() {
question_id.value++;
showResult.value = false;
}
</script>
<template>
<h1>Calculator Game</h1>
<p>Question {{ question_id }}: </p>
<Question @answer="(ans) => correct_ans = ans"/>
<!-- 為了畫面簡潔而暫時省略掉此部份的程式碼 -->
<div id="result" v-if="showResult">
<p v-if="isCorrect">Your answer is correct!</p>
<p v-else>You've answered wrong, the correct result is {{ correct_ans }}</p>
<button @click="nextQuestion">Next</button>
</div>
<p v-else>Click on the button to check your answer</p>
</template>
不過現在的程式有一個問題,那便是現在僅僅只有題號會變動,但題目仍然不會改變,為了解決這個問題,我們可以在 Question 子元件中先利用 props 將題號傳進去,並於其中使用 watcher 來根據變數的數值改變來呼叫更新題目用的函式:
<script setup>
import { ref, watch } from 'vue'
var props = defineProps({ id: Number })
const num1 = ref(Math.floor(Math.random() * 100))
const num2 = ref(Math.floor(Math.random() * 100))
var op_id = Math.floor(Math.random() * 10 % 4)
const op = ['+', '-', '*', '/']
function generate() {
num1.value = Math.floor(Math.random() * 100);
num2.value = Math.floor(Math.random() * 100);
op_id = Math.floor(Math.random() * 10 % 4);
emit('answer', calculate());
}
function calculate() {
switch (op_id) {
case 0:
return num1.value + num2.value
case 1:
return num1.value - num2.value
case 2:
return num1.value * num2.value
default:
return Math.floor(num1.value / num2.value)
}
}
const emit = defineEmits(['answer']);
emit('answer', calculate());
watch(() => props.id, () => { generate() })
</script>
不過,有以下兩點需要特別注意:
watch()
來觀察 id 的值時,需要以 () => props.id
的方式表示,否則會出現錯誤 (網頁參考)emit()
之外,我們也要在新題目生成時再次使用 emit()
將新答案傳給父函式,否則父函式所擁有的答案數值不會有所改變此部份非常的簡單,只需要建立兩個變數:score,用於紀錄分數,以及 showScore,讓程式知道要何時顯示最後分數就可以了。至於要什麼時候去更新他們的數值,前者可以新增在 ok 按鈕被按下時所呼叫的函式,那個函式正式用來判斷輸入內容是否相同,至於後者則放在 next 按鈕所呼叫的 nextQuestion,如果題目編號已經為10時,表示使用者已經回答完10個題目,也便是顯示分數的時刻了。
程式碼如下:
<script setup>
import { ref } from 'vue';
import Question from './components/Question.vue'
const player_ans = ref(Number);
const correct_ans = ref(Number);
const score = ref(0);
const question_id = ref(1);
const isCorrect = ref();
const showResult = ref(false);
const showScore = ref(false);
function onInput(e) { player_ans.value = e.target.value }
function getResult() {
isCorrect.value = (player_ans.value == correct_ans.value);
score.value += (isCorrect.value) * 10;
player_ans.value = null;
showResult.value = true
}
function nextQuestion() {
if(question_id.value == 10) {
showScore.value = true;
return;
}
question_id.value++;
showResult.value = false;
}
</script>
<template>
<h1>Calculator Game</h1>
<div id="score" v-if="showScore">
<p>Congratulations! You've finished the game!</p>
<p>Score: {{ score }} points</p>
</div>
<div v-else>
<p>Question {{ question_id }}: </p>
<Question :id="question_id" @answer="(ans) => correct_ans = ans"/>
<div id="answer">
<input type="number" id="player_ans" v-model="player_ans" placeholder="answer">
<button v-if="!showResult" @click="getResult">OK</button>
<button v-else @click="nextQuestion">Next</button>
</div>
<div id="result" v-if="showResult">
<p v-if="isCorrect">Your answer is correct!</p>
<p v-else>You've answered wrong, the correct result is {{ correct_ans }}</p>
</div>
<p v-else>Click on the button to check your answer</p>
</div>
</template>
<style scoped></style>